/**
 *
 * @author Alex
 */
public class LinkedList {

    private Node head;

    //post: has constructed an empty LinkedList
    public LinkedList(){

    }

    //post: returns true iff the list is empty
    public boolean isEmpty(){
        return head == null;
    }

    //post: returns the number of objects in the list
    public int size(){
        if(this.isEmpty())
            return 0;
        else{
            int counter = 1;
            Node node = head;

            while(!(node.getNext() == null)){
                node = node.getNext();
                counter++;
            }

            return counter;
        }
    }

    //post: has added a node to the front of the list containing el
    public void addFirst(Integer el){
        Node node = new Node(el, head);
        head = node;
    }

    //post: has added a node to the rear of the list containing el
    public void addLast(Integer el){
        Node node = head;
        Node newnode = new Node(el,null);

        while(!(node.getNext() == null)){
            node = node.getNext();
        }

        node.setNext(newnode);
    }

    //pre: !isEmpty()
    //post: if pre is true, has removed the first node and returned the
    //element of the node, has returned null otherwise
    public Integer removeFirst(){
        if(this.isEmpty()){
            return null;
        }
        else{
            Node first = head;
            head = head.getNext();
            return first.getElement();
        }
    }

    //pre: !isEmpty
    //post: if pre is true, has removed the first node and returned the
    //element of the node, has returned null otherwise
    public Integer removeLast(){
        if(this.isEmpty()){
            return null;
        }
        else{
            Node node = head;
             
            while(!(node.getNext().getNext() == null)){
                node = node.getNext();
            }

            Node last = node.getNext();
            node.setNext(null);
            return last.getElement();
        }
    }

    //post: returns the first position (from left to right) where el was
    //found, returns -1 otherwise
    public int indexOf(Integer el){
        Node node = head;
        boolean found = false;
        int counter = 0;

        while(!(node == null) && !found){
            if(node.getElement().compareTo(el) == 0){
                found = true;
            }
            else{
                counter++;
                node = node.getNext();
            }
        }

        if(found)
            return counter;
        else return -1;
    }

    //post: returns a String representation of LinkedList
    @Override
    public String toString(){
        String res = "<LinkedList[";
        Node node = head;
        int size = this.size();
        int counter = 1;

        while(!(node == null)){
            if(counter == size){
                res += node.toString();
            }
            else{
                res += node.toString() + ",";
            }
            node = node.getNext();
            counter++;
        }

        return res + "]>";
    }

    //post: returns a LinkedList that contains references to the Integers
    //of this LinkedList object, but in reversed order. This LinkedList has
    //not been changed
    public LinkedList reverse(){
        LinkedList res = new LinkedList();
        Node node = head;

        while(!(node == null)){
            res.addFirst(node.getElement());
            node = node.getNext();
        }

        return res;
    }

}